#pragma once
#include "Thread.hpp"
#include "Log.hpp"
#include "Cond.hpp"
#include "Mutex.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <queue>
using namespace std;

static const int num = 5;
template <typename T>
class ThreadPool
{
private:
    void WakeUpAllThread()
    {
        LockGuard lockguard(_mutex);
        if (_sleepnum)
            _cond.Broadcast();
        LOG(INFO) << "唤醒所有线程";
    }
    void WakeUpOne()
    {
        _cond.Signal();
        LOG(INFO) << "唤醒一个线程";
    }
    ThreadPool(int defaultnum = num)
        : _num(defaultnum), _isrunning(false), _sleepnum(0)
    {
        for (int i = 0; i < _num; i++)
        {
            _threads.emplace_back(
                [this]()
                {
                    HandlerTask();
                });
        }
    }
    void Start()//
    {
        if (_isrunning)
            return;
        _isrunning = true;
        for (auto &e : _threads)
        {
            e.Start();//
            LOG(INFO) << "start new thread success" << e.Name();
        }
    }
    ThreadPool(const ThreadPool<T> &) = delete;
    ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;

public:
    static ThreadPool<T> *GetInstance()
    {
        if (inc == nullptr)
        {
            LockGuard lockguard(_lock);
            if (inc == nullptr)
            {
                LOG(DEBUG) << "首次使用单例";
                inc = new ThreadPool<T>();
                inc->Start();//
            }
        }
        return inc;
    }
    void Stop()
    {
        if (!_isrunning)
            return;
        _isrunning = false;
        WakeUpAllThread();
    }
    void Join()
    {
        for (auto &e : _threads)
        {
            e.Join();
        }
    }
    void HandlerTask()//执行任务队列
    {
        char name[128];
        pthread_getname_np(pthread_self(), name, sizeof(name));
        while (true)
        {
            T t;
            {
                LockGuard lockguard(_mutex);
                while (_taskq.empty() && _isrunning)
                {
                    _sleepnum++;
                    _cond.Wait(_mutex);
                    _sleepnum--;
                }
                if (!_isrunning && _taskq.empty())
                {
                    LOG(INFO) << name << "退出了，线程池退出，任务队列为空";
                    break;
                }
                t = _taskq.front();
                _taskq.pop();
            }
            t();//取任务队列，执行函数
        }
    }
    bool Enqueue(const T &in)
    {
        if (_isrunning)
        {
            LockGuard lockguard(_mutex);
            _taskq.push(in);
            if (_threads.size() == _sleepnum)
            {
                WakeUpOne();
            }
            return true;
        }
        return false;
    }
    ~ThreadPool()
    {
    }

private:
    vector<Thread> _threads;
    queue<T> _taskq;
    int _num;
    Cond _cond;
    Mutex _mutex;

    bool _isrunning;
    int _sleepnum;

    static ThreadPool<T> *inc;
    static Mutex _lock;
};
template <typename T>
ThreadPool<T> *ThreadPool<T>::inc = nullptr;

template <typename T>
Mutex ThreadPool<T>::_lock;